package com.se.hospitalmonitoring;

import java.util.ArrayList;
import java.util.Date;

import com.se.hospitalmonitoring.VitalSign.VitalSignMeasurement;

public class VitalSensorInterface {

	private static VitalSensorInterface instance = null;
	private final ArrayList<VitalSensorListener> vitalSensorListeners = new ArrayList<VitalSensorListener>();
	private final ArrayList<VitalAlarmListener> vitalAlarmListeners = new ArrayList<VitalAlarmListener>();

	/**
	 * Private constructor
	 */
	private VitalSensorInterface() {
	}

	/**
	 * Gets the singleton instance of this class
	 * 
	 * @return The singleton instance of this class
	 */
	public static VitalSensorInterface getInstance() {
		if (instance == null) {
			instance = new VitalSensorInterface();
		}
		return instance;
	}

	/**
	 * Called when a new vital measurement is received
	 * 
	 * @param vs
	 *            The vital sign that was received
	 */
	public void onNewVitalMeasurementReceived(VitalSignMeasurement vs) {
		for (VitalSensorListener listener : vitalSensorListeners) {
			listener.onNewVitalMeasurement(vs);
		}
		if (vs.percentValue < vs.vitalSign.lowerBound
			|| vs.percentValue > vs.vitalSign.upperBound) {
			for (VitalAlarmListener listener : vitalAlarmListeners) {
				listener.onAlarmTriggered(vs.vitalSign);
			}
		}
	}

	/**
	 * Adds a listener that is notified when we get a new vital sign
	 * 
	 * @param listener
	 *            The listener to addd
	 */
	public void addVitalSensorListener(VitalSensorListener listener) {
		vitalSensorListeners.add(listener);
	}

	/**
	 * Removes the given listener
	 * 
	 * @param listener
	 *            The listener to remove
	 */
	public void removeVitalSensorListener(VitalSensorListener listener) {
		vitalSensorListeners.remove(listener);
	}

	/**
	 * Adds the given listener to be notified when a vital alarm is triggered
	 * 
	 * @param listener
	 *            The listener to add
	 */
	public void addVitalAlarmListener(VitalAlarmListener listener) {
		vitalAlarmListeners.add(listener);
	}

	/**
	 * Removes the given listener
	 * 
	 * @param listener
	 *            The listener to remove
	 */
	public void removeVitalAlarmListener(VitalAlarmListener listener) {
		vitalAlarmListeners.remove(listener);
	}

	/**
	 * Imitates the behavior of a vital sign sensor and periodically send vital
	 * data to the vital sensor interface
	 */
	public static class MockVitalSensor extends Thread {
		public static final VitalSign[] VITAL_SIGNS = new VitalSign[] {
			new VitalSign(1, "Blood Pressure", 20, 80, 2.4f, "mmHg"),
			new VitalSign(2, "Heart Rate", 20, 80, 1.6f, "bpm"),
			new VitalSign(3, "Temperature", 20, 80, 1.6f, "\u00b0 F") };

		private static final int MEASUREMENT_INTERVAL = 2000;
		private final int[] lastMeasurements = new int[] { 50, 50, 50 };
		private final boolean stop = false;

		/**
		 * Runs in a background thread
		 */
		@Override
		public void run() {
			while (!stop) {
				for (VitalSign vitalSign : VITAL_SIGNS) {
					VitalSensorInterface vsi = VitalSensorInterface
						.getInstance();
					int index = (int) (vitalSign.id - 1);
					lastMeasurements[index] = (int) Math
						.abs(lastMeasurements[index] + Math.random() * 5
							- Math.random() * 5);
					if (lastMeasurements[index] > 100)
						lastMeasurements[index] = 90;
					VitalSignMeasurement vsm = new VitalSignMeasurement(
						vitalSign, lastMeasurements[index], new Date());
					vsi.onNewVitalMeasurementReceived(vsm);
				}
				try {
					sleep(MEASUREMENT_INTERVAL);
				}
				catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static interface VitalSensorListener {
		void onNewVitalMeasurement(VitalSignMeasurement vitalSign);
	}

	public static interface VitalAlarmListener {
		void onAlarmTriggered(VitalSign vitalSign);
	}
}
